package de.godlike.util;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

public class WakeOnLan {
	private static final int HEADER_SIZE = 6;
	private static final int DATA_SIZE = 16 * 6;

	private static final int PORT = 9;
	private String broadcastAddress = null;
	private String macAddress = null;
	private String[] hexMacAddress = null;

	public WakeOnLan(String broadcastAddress, String macAddress)
			throws IllegalArgumentException {
		this.setBroadcastAddress(broadcastAddress);
		this.setMacAddress(macAddress);
	}

	public void awake() {
		byte[] magicPacket;
		InetAddress address;

		try {
			magicPacket = this.getMagicPacket();
			address = InetAddress.getByName(this.broadcastAddress);
			DatagramPacket packet = new DatagramPacket(magicPacket,
					magicPacket.length, address, PORT);
			DatagramSocket socket = new DatagramSocket();
			socket.send(packet);
			socket.close();
		} catch (UnknownHostException e1) {
			e1.printStackTrace();
		} catch (SocketException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private byte[] getMagicPacket() throws IllegalArgumentException {
		byte[] magicPacket = null;
		byte[] magicPacketHeader = null;
		byte[] magicPacketData = null;
		int position = 0;

		// Header bestehend aus 6 * 0xff zusammenbauen:
		// /////////////////////////////////////////////
		magicPacketHeader = new byte[HEADER_SIZE];
		for (position = 0; position < HEADER_SIZE; position++) {
			magicPacketHeader[position] = (byte) 0xff;
		}

		// Data bestehend aus 16 * MAC-Adresse ohne Doppelpunkte zusammenbauen:
		// /////////////////////////////////////////////////////////////////////
		magicPacketData = new byte[DATA_SIZE];
		position = 0;
		for (int i = 0; i < 16; i++) {
			for (int j = 0; j < 6; j++) {
				magicPacketData[position] = (byte) Integer.parseInt(
						this.hexMacAddress[j], 16);
				position++;
			}
		}

		magicPacket = new byte[HEADER_SIZE + DATA_SIZE];
		System.arraycopy(magicPacketHeader, 0, magicPacket, 0,
				magicPacketHeader.length);
		System.arraycopy(magicPacketData, 0, magicPacket, HEADER_SIZE,
				magicPacketData.length);

		return magicPacket;
	}

	public void setBroadcastAddress(String broadcastAddress) {
		this.broadcastAddress = broadcastAddress;
	}

	public void setMacAddress(String macAddress)
			throws IllegalArgumentException {
		this.macAddress = macAddress;

		this.hexMacAddress = this.macAddress.split("(\\:|\\-)");
		if (this.hexMacAddress.length != 6) {
			throw new IllegalArgumentException(
					"Die angegebene MAC-Adresse ist ungültig.");
		}
		try {
			for (String hexMacAddres : this.hexMacAddress) {
				Integer.parseInt(hexMacAddres, 16);
			}
		} catch (NumberFormatException ex) {
			throw new IllegalArgumentException(
					"Die angegebene MAC-Adresse ist ungültig.");
		}
	}

	/**
	 * @deprecated Just 4 Test!
	 * @param args
	 */
	@Deprecated
	public static void main(String[] args) {
		WakeOnLan wake = new WakeOnLan("192.168.178.255", "00:19:99:0D:67:DF");
		wake.awake();
		wake.setMacAddress("00:19:99:08:AF:47");
		wake.awake();
	}
}
